﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.IO;
using System.Net;

namespace NS_Client
{
    public interface IObservable
    {
        void Register(IObserver observer);
        void UnRegister(IObserver observer);
    }

    public struct ContentItem
    {
        private string _ContentName;
        private string _ContentDesc;
        private string _ContentID;
        private string _ContentOwner;
        private int _ContentApprovalStatus;
        private System.Drawing.Image _ContentImgPath;

        public ContentItem(string contentID, string name, string description, string owner, int approval_status, string ImgPath)
        {
            _ContentImgPath = new System.Drawing.Bitmap(15, 15);

            _ContentID = contentID;
            _ContentName = name;
            _ContentDesc = description;
            _ContentOwner = owner;
            _ContentApprovalStatus = approval_status;

            try
            {
                CommsLogic.DownloadImage(this, ImgPath);                
            }
            catch (Exception e) { System.Diagnostics.Debug.WriteLine(e); }
        }

        public string Name
        {
            get { return _ContentName; }
        }

        public string Description
        {
            get { return _ContentDesc; }
        }

        public string ID
        {
            get { return _ContentID; }
        }

        public string OwnerUsername
        {
            get { return _ContentOwner; }
        }

        public int ApprovalStatus
        {
            get { return _ContentApprovalStatus; }
        }

        public System.Drawing.Image ImagePath
        {
            get { return _ContentImgPath; }
            set { _ContentImgPath = value; }
        }

    }

    /// <summary>Observerable Model that represents a Session</summary>
    public class SessionModel : IObservable
    {
        /// <summary>Collection of current Observers</summary>
        private ArrayList ObserverCollection = new ArrayList();
        /// <summary>Idicates if its safe to modify the ObserverCollection contents</summary>
        private bool iteratingObserverCollectionFlag = false;
        /// <summary>Collection of Observers to be removed</summary>
        private ArrayList UnRegisteredObservers = new ArrayList();
        /// <summary>Collection of Observers to be Added</summary>
        private ArrayList NewRegisteredObservers = new ArrayList();

        private List<ContentItem> _ContentItems;
        private string username = "";
        private bool loggedin = false;
        private string sessionid = "";
        private string failedmsg = "";
        private ArrayList _ChatLog = new ArrayList();

        public SessionModel()
        {
            _ContentItems = new List<ContentItem>();
        }

        public ArrayList ChatLog
        {
            get { return _ChatLog; }
            set { ChatLog = value; }
        }

        public List<ContentItem> ContentItems
        {
            get { return _ContentItems; }
            set
            {
                _ContentItems = value;
                StateChanged();
            }

        }

        /// <summary>Gets or sets Username</summary>
        public string Username
        {
            get { return username; }
            set
            {
                username = value;
                StateChanged();
            }
        }

        /// <summary>Gets or sets LoggedIn status</summary>
        public bool LoggedIn
        {
            get { return loggedin; }
            set
            {
                loggedin = value;
                StateChanged();

                //if LoggedIn is set to false, reset model
                if (value == false)
                    ResetModel();
            }
        }

        /// <summary>Gets or sets FailedReason</summary>
        public string FailedReason
        {
            get { return failedmsg; }
            set
            {
                failedmsg = value;
                StateChanged();
            }
        }

        /// <summary>Gets or sets SessionID</summary>
        public string SessionID
        {
            get { return sessionid; }
            set
            {
                sessionid = value;
                StateChanged();
            }
        }

        /// <summary>Registers an Observer to the collection to be notified of state changes</summary>
        public void Register(IObserver observer)
        {
            // if iterating over ObserverCollection, add observer to NewRegisteredObservers collection to be added later
            if (iteratingObserverCollectionFlag)
                NewRegisteredObservers.Add(observer);
            // else simply add the observer
            else
                ObserverCollection.Add(observer);
        }

        /// <summary>UnRegisters an Observer from the collection</summary>
        public void UnRegister(IObserver observer)
        {
            // if iterating over ObserverCollection, add observer to UnRegisteredObservers collection to be cleaned later
            if (iteratingObserverCollectionFlag)
                UnRegisteredObservers.Add(observer);
            // else simply remove the observer
            else
                ObserverCollection.Remove(observer);
        }

        /// <summary>Resets the data representing the model</summary>
        /// <remarks>Does clear collection of Observers</remarks>
        public void ResetModel()
        {
            username = SessionID = failedmsg = "";
            loggedin = false;
            _ContentItems = new List<ContentItem>();
        }

        /// <summary>Notifies Observers of state change</summary>
        private void StateChanged()
        {
            try
            {
                // inidicates we shouldn't modify ObserverCollection collection while iterating
                iteratingObserverCollectionFlag = true;

                foreach (IObserver watcher in ObserverCollection)
                {
                    watcher.notify(this);
                }

                // remove Observers that were added to UnRegisteredObservers collection while iterating
                foreach (IObserver oldwatcher in UnRegisteredObservers)
                    ObserverCollection.Remove(oldwatcher);

                // add Observers that were added to NewRegisteredObservers collection while iterating
                foreach (IObserver newwatcher in NewRegisteredObservers)
                    ObserverCollection.Add(newwatcher);

                // fine to modify ObserverCollection
                iteratingObserverCollectionFlag = false;
            }
            catch (Exception InvalidOpEx)
            {
                // System.Diagnostics.Debug.WriteLine(InvalidOpEx);
            }
        }
    }
}
